home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue26 / chessbrd / CHESSBRD.ZIP / CPP / CHTHREAD.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-08  |  33.4 KB  |  1,152 lines

  1. //---------------------------------------------------------------------------
  2. #include <vcl\vcl.h>
  3. #pragma hdrstop
  4.  
  5. #include "CHESSBRD.H"
  6. #include "CHTHREAD.H"
  7.  
  8.  
  9. // Invokes the thread  at once
  10. __fastcall ChessThread::ChessThread(char *position, bool *whitetomove,
  11.     Square *enpassant, CastleSet *castling, bool *thinking,
  12.     int *searchdepth, MoveFunc move) : TThread(false)
  13. {
  14.     StopThinkingNow=FALSE;
  15.     Thinking=thinking;
  16.     Position=position;
  17.     WhiteToMove=whitetomove;
  18.     EnPassant=enpassant;
  19.     Castling=castling;
  20.     SearchDepth=searchdepth;
  21.     Move=move;
  22.  
  23.     InitValues();
  24. }
  25.  
  26. //---------------------------------------------------------------------------
  27. void __fastcall ChessThread::Execute()
  28. {
  29.     int i;
  30.     int v;
  31.  
  32.     // Should use WaitForSingleObject(...) - but how ?
  33.     for (;;)
  34.     {
  35.         if (Terminated) break;
  36.  
  37.         if (*Thinking==TRUE)
  38.         {
  39.             for(int r=0;r<64;r++)
  40.             {
  41.                 v=ColorOfPiece((Square)(r+1));
  42.                 if      (v==Black) color[r]=DARK;
  43.                 else if (v==White) color[r]=LIGHT;
  44.                 else color[r]=EMPTY;
  45.  
  46.                 switch (Position[r+1])
  47.                 {
  48.                     case 'P':
  49.                     case 'p':{piece[r]=PAWN;  break;}
  50.                     case 'N':
  51.                     case 'n':{piece[r]=KNIGHT;break;}
  52.                     case 'B':
  53.                     case 'b':{piece[r]=BISHOP;break;}
  54.                     case 'R':
  55.                     case 'r':{piece[r]=ROOK;  break;}
  56.                     case 'Q':
  57.                     case 'q':{piece[r]=QUEEN; break;}
  58.                     case 'K':
  59.                     case 'k':{piece[r]=KING;  break;}
  60.                     default: {piece[r]=EMPTY; break;}
  61.                 }
  62.             }
  63.  
  64.         if (*WhiteToMove)
  65.             {
  66.                 side=LIGHT;
  67.                 xside=DARK;
  68.             }
  69.             else
  70.             {
  71.                 side=DARK;
  72.                 xside=LIGHT;
  73.             }
  74.  
  75.             castle=0;
  76.             if (Castling->Contains(WhiteKingSide))
  77.                 castle|=1;
  78.             if (Castling->Contains(WhiteQueenSide))
  79.                 castle|=2;
  80.             if (Castling->Contains(BlackKingSide))
  81.                 castle|=4;
  82.             if (Castling->Contains(BlackQueenSide))
  83.                 castle|=8;
  84.  
  85.             ep=*EnPassant-1;
  86.             fifty=0;
  87.             ply=0;
  88.             gen_begin[0]=0;
  89.  
  90.             nodes=0;
  91.             init_eval();
  92.             memset(history,0,sizeof(history));
  93.  
  94.             follow_pv=TRUE;
  95.  
  96.             for(i=1;i<=*SearchDepth;i++)
  97.             {
  98.                     follow_pv=TRUE;
  99.                     search(-10000,10000,i);
  100.                     if (StopThinkingNow) break;
  101.             }
  102.  
  103.             if (StopThinkingNow)
  104.             {
  105.                  *Thinking=FALSE;
  106.             }
  107.             else
  108.             {
  109.                 makemove(pv[0][0].b);
  110.                 gen();
  111.                 Synchronize(PerformMove);
  112.             }
  113.         }
  114.     }
  115.  
  116.     WaitFor();
  117. }
  118.  
  119. void __fastcall ChessThread::CancelThinking(void)
  120. {
  121.     StopThinkingNow=TRUE;
  122.     while (*Thinking) {} //Think
  123.     StopThinkingNow=FALSE;
  124. }
  125.  
  126. // Synchronizer - Modifies VCL
  127. void __fastcall ChessThread::PerformMove(void)
  128. {
  129.     if (Terminated) WaitFor();
  130.  
  131.     //Move expects *Thinking to be FALSE
  132.     *Thinking=FALSE;
  133.     if (Move (Square(pv[0][0].b.from+1),Square(pv[0][0].b.to+1))==FALSE)
  134.     {
  135.         Application->MessageBox("Engine tried to perform Illegal Move","Error",IDOK);
  136.         WaitFor();
  137.     }
  138. }
  139.  
  140. //-------------------------------------------------------------------------
  141.  
  142.  
  143. void __fastcall ChessThread::IntCopy (int *dest, const int *source, int count)
  144. {
  145.     const int *org=source;
  146.     if (dest==NULL || source==NULL) return;
  147.     for (;source<(org+count);source++,dest++)
  148.     {
  149.         *dest=*source;
  150.     }
  151.  
  152.     return;
  153. }
  154.  
  155.  
  156. int  __fastcall ChessThread::ColorOfPiece (Square sq)
  157. {
  158.     if ((Position[sq]>='b')&&(Position[sq]<='r')) return Black;
  159.     else if ((Position[sq]>='B')&&(Position[sq]<='R')) return White;
  160.     else return NoPiece;
  161. }
  162.  
  163. /* sort_pv() is called when the search function is following
  164.    the PV (Principal Variation). It looks through the current
  165.    ply's move list to see if the PV move is there. If so,
  166.    it adds 10,000,000 to the move's score so it's played first
  167.    by the search function. If not, follow_pv remains FALSE and
  168.    search() stops calling sort_pv(). */
  169.  
  170. void __fastcall ChessThread::sort_pv(void)
  171. {
  172.     int i;
  173.  
  174.     follow_pv=FALSE;
  175.     for(i=gen_begin[ply];i<gen_end[ply];i++)
  176.         if(gen_dat[i].m.i==pv[0][ply].i) {
  177.             follow_pv=TRUE;
  178.             gen_dat[i].score+=10000000;
  179.             return;
  180.         }
  181. }
  182.  
  183.  
  184. /* sort() searches the current ply's move list from 'from'
  185.    to the end to find the move with the highest score. Then it
  186.    swaps that move and the 'from' move so the move with the
  187.    highest score gets searched next, and hopefully produces
  188.    a cutoff. */
  189.  
  190. void __fastcall ChessThread::sort(int from)
  191. {
  192.     int i;
  193.     int bs;  /* best score */
  194.     int bi;  /* best i */
  195.     gen_rec g;
  196.  
  197.     bs=-1;
  198.     for(i=from;i<gen_end[ply];i++)
  199.         if(gen_dat[i].score>bs) {
  200.             bs=gen_dat[i].score;
  201.             bi=i;
  202.         }
  203.     g=gen_dat[from];
  204.     gen_dat[from]=gen_dat[bi];
  205.     gen_dat[bi]=g;
  206. }
  207.  
  208.  
  209. /* quiesce() is a recursive minimax search function with
  210.    alpha-beta cutoffs. In other words, negamax. It basically
  211.    only searches capture sequences and allows the evaluation
  212.    function to cut the search off (and set alpha). The idea
  213.    is to find a position where there isn't a lot going on
  214.    so the static evaluation function will work. */
  215.  
  216. int __fastcall ChessThread::quiesce(int alpha,int beta)
  217. {
  218.     int i,j,x;
  219.     BOOL c;  /* in check */
  220.     BOOL f;  /* legal move found */
  221.  
  222.     nodes++;
  223.     pv_length[ply]=ply;
  224.     c=in_check(side);
  225.  
  226.     /* if we're in check, try all moves to get out. (not
  227.        necessary, just something I decided to do) */
  228.     if(c)
  229.         gen();
  230.  
  231.     /* otherwise, use the evaluation function. */
  232.     else {
  233.         x=eval();
  234.         if(x>=beta)
  235.             return(beta);
  236.         if(x>alpha)
  237.             alpha=x;
  238.         gen_caps();
  239.     }
  240.     if(follow_pv)  /* are we following the PV? */
  241.         sort_pv();
  242.     f=FALSE;
  243.  
  244.     /* loop through the moves */
  245.     for(i=gen_begin[ply];i<gen_end[ply];i++) {
  246.         sort(i);
  247.         if(!makemove(gen_dat[i].m.b))
  248.             continue;
  249.         f=TRUE;  /* we found a legal move! */
  250.         x=-quiesce(-beta,-alpha);
  251.         takeback();
  252.         if(x>alpha) {
  253.             if(x>=beta)
  254.                 return(beta);
  255.             alpha=x;
  256.  
  257.             /* update the PV */
  258.             pv[ply][ply]=gen_dat[i].m;
  259.             for(j=ply+1;j<pv_length[ply+1];j++)
  260.                 pv[ply][j]=pv[ply+1][j];
  261.             pv_length[ply]=pv_length[ply+1];
  262.         }
  263.     }
  264.  
  265.     /* if we're in check and there aren't any legal moves,
  266.        well, we lost */
  267.     if((!f)&&c)
  268.         return(-10000+ply);
  269.     return(alpha);
  270. }
  271.  
  272.  
  273. /* search() does just that, in negamax fashion */
  274.  
  275. int __fastcall ChessThread::search(int alpha,int beta,int depth)
  276. {
  277.     int i,j,x;
  278.     BOOL c,f;
  279.  
  280.     /* we're as deep as we want to be; call quiesce() to get
  281.        a reasonable score and return it. */
  282.     if(!depth)
  283.         return(quiesce(alpha,beta));
  284.     nodes++;
  285.     pv_length[ply]=ply;
  286.  
  287.     /* are we in check? if so, we want to search deeper */
  288.     c=in_check(side);
  289.     if(c)
  290.         depth++;
  291.     gen();
  292.     if(follow_pv)  /* are we following the PV? */
  293.         sort_pv();
  294.     f=FALSE;
  295.  
  296.     /* loop through the moves */
  297.     for(i=gen_begin[ply];i<gen_end[ply];i++) {
  298.         sort(i);
  299.         if(!makemove(gen_dat[i].m.b))
  300.             continue;
  301.  
  302.         //
  303.         if (StopThinkingNow) return -1;
  304.  
  305.         f=TRUE;
  306.         x=-search(-beta,-alpha,depth-1);
  307.         takeback();
  308.         if(x>alpha) {
  309.  
  310.             /* this move caused a cutoff, so increase the history
  311.                value so it gets ordered high next time we can
  312.                search it */
  313.             history[gen_dat[i].m.b.from][gen_dat[i].m.b.to]+=depth;
  314.             if(x>=beta)
  315.                 return(beta);
  316.             alpha=x;
  317.  
  318.             /* update the PV */
  319.             pv[ply][ply]=gen_dat[i].m;
  320.             for(j=ply+1;j<pv_length[ply+1];j++)
  321.                 pv[ply][j]=pv[ply+1][j];
  322.             pv_length[ply]=pv_length[ply+1];
  323.         }
  324.     }
  325.  
  326.     /* no legal moves? then we're in checkmate or stalemate */
  327.     if(!f) {
  328.         if(c)
  329.             return(-10000+ply);
  330.         else
  331.             return(0);
  332.     }
  333.  
  334.     /* fifty move draw rule */
  335.     if(fifty>100)
  336.         return(0);
  337.     return(alpha);
  338. }
  339.  
  340.  
  341. /* think() calls search() iteratively and prints the results
  342.    after every iteration. */
  343.  
  344. void __fastcall ChessThread::think(void)
  345. {
  346.     int i,j,x;
  347.  
  348.     ply=0;
  349.     nodes=0;
  350.     init_eval();
  351.     memset(history,0,sizeof(history));
  352.     printf("ply      nodes  score  pv\n");
  353.     for(i=1;i<=4;i++) {
  354.         follow_pv=TRUE;
  355.         x=search(-10000,10000,i);
  356.         printf("%3d  %9d  %5d ",i,nodes,x);
  357.         for(j=0;j<pv_length[0];j++)
  358.         {
  359.             printf(" %c%d%c%d",
  360.                     FILE(pv[0][j].b.from)+'a',
  361.                     8-RANK(pv[0][j].b.from),
  362.                     FILE(pv[0][j].b.to)+'a',
  363.                     8-RANK(pv[0][j].b.to));
  364.         }
  365.         printf("\n");
  366.     }
  367. }
  368.  
  369. /* init() sets the board to the initial game state */
  370.  
  371. void __fastcall ChessThread::init(void)
  372. {
  373.     int i;
  374.  
  375.     for(i=0;i<64;i++) {
  376.         color[i]=init_color[i];
  377.         piece[i]=init_piece[i];
  378.     }
  379.     side=LIGHT;
  380.     xside=DARK;
  381.     castle=15;
  382.     ep=-1;
  383.     fifty=0;
  384.     ply=0;
  385.     gen_begin[0]=0;
  386. }
  387.  
  388.  
  389. /* in_check() returns TRUE if side s is in check and FALSE
  390.    otherwise. It just scans the board to find side s's king
  391.    and calls attack() to see if it's being attacked. */
  392.  
  393. BOOL __fastcall ChessThread::in_check(int s)
  394. {
  395.     int i;
  396.  
  397.     for(i=0;i<64;i++)
  398.         if(color[i]==s&&piece[i]==KING)
  399.             return(attack(i,s^1));
  400.     return FALSE;
  401. }
  402.  
  403.  
  404. /* attack returns TRUE if square sq is being attacked by side
  405.    s and FALSE otherwise. */
  406.  
  407. BOOL __fastcall ChessThread::attack(int sq,int s)
  408. {
  409.     int i,j,n;
  410.  
  411.     for(i=0;i<64;i++)
  412.         if(color[i]==s) {
  413.             if(piece[i]==PAWN) {
  414.                 if(s==LIGHT) {
  415.                     if(FILE(i)!=0&&i-9==sq)
  416.                         return(TRUE);
  417.                     if(FILE(i)!=7&&i-7==sq)
  418.                         return(TRUE);
  419.                 }
  420.                 else {
  421.                     if(FILE(i)!=0&&i+7==sq)
  422.                         return(TRUE);
  423.                     if(FILE(i)!=7&&i+9==sq)
  424.                         return(TRUE);
  425.                 }
  426.             }
  427.             else
  428.                 for(j=0;j<offsets[piece[i]];j++)
  429.                     for(n=i;;) {
  430.                         n=mailbox[mailbox64[n]+offset[piece[i]][j]];
  431.                         if(n==-1)
  432.                             break;
  433.                         if(n==sq)
  434.                             return(TRUE);
  435.                         if(color[n]!=EMPTY)
  436.                             break;
  437.                         if(!slide[piece[i]])
  438.                             break;
  439.                     }
  440.         }
  441.     return(FALSE);
  442. }
  443.  
  444.  
  445. /* gen() generates pseudo-legal moves for the current position.
  446.    It scans the board to find friendly pieces and then determines
  447.    what squares they attack. When it finds a piece/square
  448.    combination, it calls gen_push to put the move on the "move
  449.    stack." */
  450.  
  451. void __fastcall ChessThread::gen(void)
  452. {
  453.     int i,j,n;
  454.  
  455.     /* so far, we have no moves for the current ply */
  456.     gen_end[ply]=gen_begin[ply];
  457.     for(i=0;i<64;i++)
  458.         if(color[i]==side) {
  459.             if(piece[i]==PAWN) {
  460.                 if(side==LIGHT) {
  461.                     if(FILE(i)!=0&&color[i-9]==DARK)
  462.                         gen_push(i,i-9,17);
  463.                     if(FILE(i)!=7&&color[i-7]==DARK)
  464.                         gen_push(i,i-7,17);
  465.                     if(color[i-8]==EMPTY) {
  466.                         gen_push(i,i-8,16);
  467.                         if(i>=48&&color[i-16]==EMPTY)
  468.                             gen_push(i,i-16,24);
  469.                     }
  470.                 }
  471.                 else {
  472.                     if(FILE(i)!=0&&color[i+7]==LIGHT)
  473.                         gen_push(i,i+7,17);
  474.                     if(FILE(i)!=7&&color[i+9]==LIGHT)
  475.                         gen_push(i,i+9,17);
  476.                     if(color[i+8]==EMPTY) {
  477.                         gen_push(i,i+8,16);
  478.                         if(i<=15&&color[i+16]==EMPTY)
  479.                             gen_push(i,i+16,24);
  480.                     }
  481.                 }
  482.             }
  483.             else
  484.                 for(j=0;j<offsets[piece[i]];j++)
  485.                     for(n=i;;) {
  486.                         n=mailbox[mailbox64[n]+offset[piece[i]][j]];
  487.                         if(n==-1)
  488.                             break;
  489.                         if(color[n]!=EMPTY) {
  490.                             if(color[n]==xside)
  491.                                 gen_push(i,n,1);
  492.                             break;
  493.                         }
  494.                         gen_push(i,n,0);
  495.                         if(!slide[piece[i]])
  496.                             break;
  497.                     }
  498.         }
  499.  
  500.     /* generate castle moves */
  501.     if(side==LIGHT) {
  502.         if(castle&1)
  503.             gen_push(60,62,2);
  504.         if(castle&2)
  505.             gen_push(60,58,2);
  506.     }
  507.     else {
  508.         if(castle&4)
  509.             gen_push(4,6,2);
  510.         if(castle&8)
  511.             gen_push(4,2,2);
  512.     }
  513.  
  514.     /* generate en passant moves */
  515.     if(ep!=-1) {
  516.         if(side==LIGHT) {
  517.             if(FILE(ep)!=0&&color[ep+7]==LIGHT&&piece[ep+7]==PAWN)
  518.                 gen_push(ep+7,ep,21);
  519.             if(FILE(ep)!=7&&color[ep+9]==LIGHT&&piece[ep+9]==PAWN)
  520.                 gen_push(ep+9,ep,21);
  521.         }
  522.         else {
  523.             if(FILE(ep)!=0&&color[ep-9]==DARK&&piece[ep-9]==PAWN)
  524.                 gen_push(ep-9,ep,21);
  525.             if(FILE(ep)!=7&&color[ep-7]==DARK&&piece[ep-7]==PAWN)
  526.                 gen_push(ep-7,ep,21);
  527.         }
  528.     }
  529.  
  530.     /* the next ply's moves need to start where the current
  531.        ply's end */
  532.     gen_begin[ply+1]=gen_end[ply];
  533. }
  534.  
  535.  
  536. /* gen_caps() is basically a copy of gen() that's modified to
  537.    only generate capture and promote moves. It's used by the
  538.    quiescence search. */
  539.  
  540. void __fastcall ChessThread::gen_caps(void)
  541. {
  542.     int i,j,n;
  543.  
  544.     gen_end[ply]=gen_begin[ply];
  545.     for(i=0;i<64;i++)
  546.         if(color[i]==side) {
  547.             if(piece[i]==PAWN) {
  548.                 if(side==LIGHT) {
  549.                     if(FILE(i)!=0&&color[i-9]==DARK)
  550.                         gen_push(i,i-9,17);
  551.                     if(FILE(i)!=7&&color[i-7]==DARK)
  552.                         gen_push(i,i-7,17);
  553.                     if(i<=15&&color[i-8]==EMPTY)
  554.                         gen_push(i,i-8,16);
  555.                 }
  556.                 if(side==DARK) {
  557.                     if(FILE(i)!=0&&color[i+7]==LIGHT)
  558.                         gen_push(i,i+7,17);
  559.                     if(FILE(i)!=7&&color[i+9]==LIGHT)
  560.                         gen_push(i,i+9,17);
  561.                     if(i>=48&&color[i+8]==EMPTY)
  562.                         gen_push(i,i+8,16);
  563.                 }
  564.             }
  565.             else
  566.                 for(j=0;j<offsets[piece[i]];j++)
  567.                     for(n=i;;) {
  568.                         n=mailbox[mailbox64[n]+offset[piece[i]][j]];
  569.                         if(n==-1)
  570.                             break;
  571.                         if(color[n]!=EMPTY) {
  572.                             if(color[n]==xside)
  573.                                 gen_push(i,n,1);
  574.                             break;
  575.                         }
  576.                         if(!slide[piece[i]])
  577.                             break;
  578.                     }
  579.         }
  580.     if(ep!=-1) {
  581.         if(side==LIGHT) {
  582.             if(FILE(ep)!=0&&color[ep+7]==LIGHT&&piece[ep+7]==PAWN)
  583.                 gen_push(ep+7,ep,21);
  584.             if(FILE(ep)!=7&&color[ep+9]==LIGHT&&piece[ep+9]==PAWN)
  585.                 gen_push(ep+9,ep,21);
  586.         }
  587.         else {
  588.             if(FILE(ep)!=0&&color[ep-9]==DARK&&piece[ep-9]==PAWN)
  589.                 gen_push(ep-9,ep,21);
  590.             if(FILE(ep)!=7&&color[ep-7]==DARK&&piece[ep-7]==PAWN)
  591.                 gen_push(ep-7,ep,21);
  592.         }
  593.     }
  594.     gen_begin[ply+1]=gen_end[ply];
  595. }
  596.  
  597.  
  598. /* gen_push() puts a move on the move stack, unless it's a
  599.    pawn promotion that needs to be handled by gen_promote().
  600.    It also assigns a score to the move for alpha-beta move
  601.    ordering. If the move is a capture, it uses MVV/LVA
  602.    (Most Valuable Victim/Least Valuable Attacker). Otherwise,
  603.    it uses the move's history heuristic value. Note that
  604.    1,000,000 is added to a capture move's score, so it
  605.    always gets ordered above a "normal" move. */
  606.  
  607. void __fastcall ChessThread::gen_push(int from,int to,int bits)
  608. {
  609.     gen_rec *g;
  610.  
  611.     if(bits&16) {
  612.         if(side==LIGHT) {
  613.             if(to<=8) {
  614.                 gen_promote(from,to,bits);
  615.                 return;
  616.             }
  617.         }
  618.         else {
  619.             if(to>=56) {
  620.                 gen_promote(from,to,bits);
  621.                 return;
  622.             }
  623.         }
  624.     }
  625.     g=&gen_dat[gen_end[ply]];
  626.     gen_end[ply]++;
  627.     g->m.b.from=char(from);
  628.     g->m.b.to=char(to);
  629.     g->m.b.promote=0;
  630.     g->m.b.bits=char(bits);
  631.     if(bits&1)
  632.         g->score=1000000+(piece[to]*10)-piece[from];
  633.     else
  634.         g->score=history[from][to];
  635. }
  636.  
  637.  
  638. /* gen_promote() is just like gen_push(), only it puts 4 moves
  639.    on the move stack, one for each possible promotion piece */
  640.  
  641. void __fastcall ChessThread::gen_promote(int from,int to,int bits)
  642. {
  643.     int i;
  644.     gen_rec *g;
  645.  
  646.     for(i=KNIGHT;i<=QUEEN;i++) {
  647.         g=&gen_dat[gen_end[ply]];
  648.         gen_end[ply]++;
  649.         g->m.b.from=char(from);
  650.         g->m.b.to=char(to);
  651.         g->m.b.promote=char(i);
  652.         g->m.b.bits=char(bits|32);
  653.         g->score=1000000+(i*10);
  654.     }
  655. }
  656.  
  657.  
  658. /* makemove() makes a move. If the move is illegal, it
  659.    undoes whatever it did and returns FALSE. Otherwise, it
  660.    returns TRUE. */
  661.  
  662. BOOL __fastcall ChessThread::makemove(move_bytes m)
  663. {
  664.  
  665.     /* test to see if a castle move is legal and move the rook
  666.        (the king is moved with the usual move code later) */
  667.     if(m.bits&2) {
  668.         if(in_check(side))
  669.             return(FALSE);
  670.         switch(m.to) {
  671.             case 62:
  672.                 if(color[61]!=EMPTY||color[62]!=EMPTY||
  673.                         attack(61,xside)||attack(62,xside))
  674.                     return(FALSE);
  675.                 color[61]=LIGHT;
  676.                 piece[61]=ROOK;
  677.                 color[63]=EMPTY;
  678.                 piece[63]=EMPTY;
  679.                 break;
  680.             case 58:
  681.                 if(color[57]!=EMPTY||color[58]!=EMPTY||color[59]!=EMPTY||
  682.                         attack(58,xside)||attack(59,xside))
  683.                     return(FALSE);
  684.                 color[59]=LIGHT;
  685.                 piece[59]=ROOK;
  686.                 color[56]=EMPTY;
  687.                 piece[56]=EMPTY;
  688.                 break;
  689.             case 6:
  690.                 if(color[5]!=EMPTY||color[6]!=EMPTY||
  691.                         attack(5,xside)||attack(6,xside))
  692.                     return(FALSE);
  693.                 color[5]=DARK;
  694.                 piece[5]=ROOK;
  695.                 color[7]=EMPTY;
  696.                 piece[7]=EMPTY;
  697.                 break;
  698.             case 2:
  699.                 if(color[1]!=EMPTY||color[2]!=EMPTY||color[3]!=EMPTY||
  700.                         attack(2,xside)||attack(3,xside))
  701.                     return(FALSE);
  702.                 color[3]=DARK;
  703.                 piece[3]=ROOK;
  704.                 color[0]=EMPTY;
  705.                 piece[0]=EMPTY;
  706.                 break;
  707.         }
  708.     }
  709.  
  710.     /* back up information so we can take the move back later. */
  711.     hist_dat[ply].m.b=m;
  712.     hist_dat[ply].capture=piece[m.to];
  713.     hist_dat[ply].castle=castle;
  714.     hist_dat[ply].ep=ep;
  715.     hist_dat[ply].fifty=fifty;
  716.     ply++;
  717.  
  718.     /* update the castle, en passant, and
  719.        fifty-move-draw variables */
  720.     castle&=castle_mask[m.from]&castle_mask[m.to];
  721.     if(m.bits&8) {
  722.         if(side==LIGHT)
  723.             ep=m.to+8;
  724.         else
  725.             ep=m.to-8;
  726.     }
  727.     else
  728.         ep=-1;
  729.     if(m.bits&17)
  730.         fifty=0;
  731.     else
  732.         fifty++;
  733.  
  734.     /* move the piece */
  735.     color[m.to]=side;
  736.     if(m.bits&32)
  737.         piece[m.to]=m.promote;
  738.     else
  739.         piece[m.to]=piece[m.from];
  740.     color[m.from]=EMPTY;
  741.     piece[m.from]=EMPTY;
  742.  
  743.     /* erase the pawn if this is an en passant move */
  744.     if(m.bits&4) {
  745.         if(side==LIGHT) {
  746.             color[m.to+8]=EMPTY;
  747.             piece[m.to+8]=EMPTY;
  748.         }
  749.         else {
  750.             color[m.to-8]=EMPTY;
  751.             piece[m.to-8]=EMPTY;
  752.         }
  753.     }
  754.  
  755.     /* switch sides and test for legality (if we can capture
  756.        the other guy's king, it's an illegal position and
  757.        we need to take the move back) */
  758.     side^=1;
  759.     xside^=1;
  760.     if(in_check(xside)) {
  761.         takeback();
  762.         return(FALSE);
  763.     }
  764.     return(TRUE);
  765. }
  766.  
  767.  
  768. /* takeback() is very similar to makemove(), only backwards :)  */
  769.  
  770. void __fastcall ChessThread::takeback(void)
  771. {
  772.     move_bytes m;
  773.  
  774.     side^=1;
  775.     xside^=1;
  776.     ply--;
  777.     m=hist_dat[ply].m.b;
  778.     castle=hist_dat[ply].castle;
  779.     ep=hist_dat[ply].ep;
  780.     fifty=hist_dat[ply].fifty;
  781.     color[m.from]=side;
  782.     if(m.bits&32)
  783.         piece[m.from]=PAWN;
  784.     else
  785.         piece[m.from]=piece[m.to];
  786.     if(hist_dat[ply].capture==EMPTY) {
  787.         color[m.to]=EMPTY;
  788.         piece[m.to]=EMPTY;
  789.     }
  790.     else {
  791.         color[m.to]=xside;
  792.         piece[m.to]=hist_dat[ply].capture;
  793.     }
  794.     if(m.bits&2) {
  795.         int from,to;
  796.  
  797.         switch(m.to) {
  798.             case 62: from=61; to=63; break;
  799.             case 58: from=59; to=56; break;
  800.             case 6: from=5; to=7; break;
  801.             case 2: from=3; to=0; break;
  802.         }
  803.         color[to]=side;
  804.         piece[to]=ROOK;
  805.         color[from]=EMPTY;
  806.         piece[from]=EMPTY;
  807.     }
  808.     if(m.bits&4) {
  809.         if(side==LIGHT) {
  810.             color[m.to+8]=xside;
  811.             piece[m.to+8]=PAWN;
  812.         }
  813.         else {
  814.             color[m.to-8]=xside;
  815.             piece[m.to-8]=PAWN;
  816.         }
  817.     }
  818. }
  819.  
  820. int __fastcall ChessThread::eval(void)
  821. {
  822.     int i;
  823.     int c;  /* color */
  824.     int xc;  /* not c */
  825.     int f;  /* file */
  826.     int score[2];  /* the score for each side */
  827.     int pawns[2][10];  /* the number of pawns of each color on each file */
  828.  
  829.     score[LIGHT]=score[DARK]=0;
  830.     memset(pawns,0,sizeof(pawns));
  831.  
  832.     /* loop through to set up the pawns array and to add up the
  833.        piece/square table values for each piece. */
  834.     for(i=0;i<64;i++) {
  835.         if(color[i]==EMPTY)
  836.             continue;
  837.         if(piece[i]==PAWN)
  838.             pawns[color[i]][FILE(i)+1]++;
  839.         score[color[i]]+=pcsq[color[i]][piece[i]][i];
  840.     }
  841.  
  842.     /* now that we have the pawns array set up, evaluate the pawns
  843.        and rooks */
  844.     for(i=0;i<64;i++) {
  845.         if(color[i]==EMPTY)
  846.             continue;
  847.         c=color[i];  /* set up c, xc, and f so we don't have to type a lot */
  848.         xc=c^1;
  849.         f=FILE(i)+1;
  850.         if(piece[i]==PAWN) {
  851.             if(pawns[c][f]>1)  /* this pawn is doubled */
  852.                 score[c]-=5;
  853.             if((!pawns[c][f-1])&&
  854.                     (!pawns[c][f+1])) {  /* isolated */
  855.                 score[c]-=20;
  856.                 if(!pawns[xc][f])
  857.                     score[c]-=10;
  858.             }
  859.             if((!pawns[xc][f-1])&&  /* passed */
  860.                     (!pawns[xc][f])&&
  861.                     (!pawns[xc][f+1]))
  862.                 score[c]+=2*pcsq[c][PAWN][i];
  863.         }
  864.         if(piece[i]==ROOK)
  865.             if(!pawns[c][f]) {  /* the rook is on a half-open file */
  866.                 score[c]+=10;
  867.                 if(!pawns[xc][f])  /* actually, it's totally open */
  868.                     score[c]+=5;
  869.             }
  870.     }
  871.  
  872.     /* return the score relative to the side to move (i.e.,
  873.        a positive score means the side to move is winning) */
  874.     if(side==LIGHT)
  875.         return(score[LIGHT]-score[DARK]);
  876.     return(score[DARK]-score[LIGHT]);
  877. }
  878.  
  879. void __fastcall ChessThread::init_eval(void)
  880. {
  881.     int i,material,king_sq;
  882.  
  883.     memset(pcsq,0,sizeof(pcsq));
  884.  
  885.     /* initialize the no-brainer piece/square tables */
  886.     for(i=0;i<64;i++) {
  887.         pcsq[LIGHT][PAWN][i]=value[PAWN]+pawn_pcsq[i];
  888.         pcsq[LIGHT][KNIGHT][i]=value[KNIGHT]+minor_pcsq[i];
  889.         pcsq[LIGHT][BISHOP][i]=value[BISHOP]+minor_pcsq[i];
  890.         pcsq[LIGHT][ROOK][i]=value[ROOK];
  891.         pcsq[LIGHT][QUEEN][i]=value[QUEEN];
  892.         pcsq[DARK][PAWN][i]=value[PAWN]+pawn_pcsq[flip[i]];
  893.         pcsq[DARK][KNIGHT][i]=value[KNIGHT]+minor_pcsq[flip[i]];
  894.         pcsq[DARK][BISHOP][i]=value[BISHOP]+minor_pcsq[flip[i]];
  895.         pcsq[DARK][ROOK][i]=value[ROOK];
  896.         pcsq[DARK][QUEEN][i]=value[QUEEN];
  897.     }
  898.  
  899.     /* now scan the board to see how much piece material the
  900.        enemy has and figure out what side of the board the
  901.        king is on */
  902.     material=0;
  903.     for(i=0;i<64;i++) {
  904.         if(color[i]==DARK&&piece[i]!=PAWN)
  905.             material+=value[piece[i]];
  906.         if(color[i]==LIGHT&&piece[i]==KING)
  907.             king_sq=i;
  908.     }
  909.     if(material>1400) {  /* use the middlegame tables */
  910.         for(i=0;i<64;i++)
  911.             pcsq[LIGHT][KING][i]=king_pcsq[i];
  912.         if(FILE(king_sq)>=5)
  913.             for(i=0;i<64;i++)
  914.                 pcsq[LIGHT][PAWN][i]+=kingside_pawn_pcsq[i];
  915.         if(FILE(king_sq)<=2)
  916.             for(i=0;i<64;i++)
  917.                 pcsq[LIGHT][PAWN][i]+=queenside_pawn_pcsq[i];
  918.     }
  919.     else
  920.         for(i=0;i<64;i++)
  921.             pcsq[LIGHT][KING][i]=endgame_king_pcsq[i];
  922.  
  923.     /* do the same for black */
  924.     material=0;
  925.     for(i=0;i<64;i++) {
  926.         if(color[i]==LIGHT&&piece[i]!=PAWN)
  927.             material+=value[piece[i]];
  928.         if(color[i]==DARK&&piece[i]==KING)
  929.             king_sq=i;
  930.     }
  931.     if(material>1400) {
  932.         for(i=0;i<64;i++)
  933.             pcsq[DARK][KING][i]=king_pcsq[flip[i]];
  934.         if(FILE(king_sq)>=5)
  935.             for(i=0;i<64;i++)
  936.                 pcsq[DARK][PAWN][i]+=kingside_pawn_pcsq[flip[i]];
  937.         if(FILE(king_sq)<=2)
  938.             for(i=0;i<64;i++)
  939.                 pcsq[DARK][PAWN][i]+=queenside_pawn_pcsq[flip[i]];
  940.     }
  941.     else
  942.         for(i=0;i<64;i++)
  943.             pcsq[DARK][KING][i]=endgame_king_pcsq[flip[i]];
  944. }
  945.  
  946.  
  947. //---------------------------------------------------------------------------
  948. void __fastcall ChessThread::InitValues()
  949. {
  950.     int _flip[64]=
  951.        {
  952.              56,  57,  58,  59,  60,  61,  62,  63,
  953.              48,  49,  50,  51,  52,  53,  54,  55,
  954.              40,  41,  42,  43,  44,  45,  46,  47,
  955.              32,  33,  34,  35,  36,  37,  38,  39,
  956.              24,  25,  26,  27,  28,  29,  30,  31,
  957.              16,  17,  18,  19,  20,  21,  22,  23,
  958.               8,   9,  10,  11,  12,  13,  14,  15,
  959.               0,   1,   2,   3,   4,   5,   6,   7
  960.         };
  961.  
  962.     IntCopy (&flip[0],&_flip[0],64);
  963.  
  964.     int _pawn_pcsq[64]= {
  965.               0,   0,   0,   0,   0,   0,   0,   0,
  966.               5,  10,  15,  20,  20,  15,  10,   5,
  967.               4,   8,  12,  16,  16,  12,   8,   4,
  968.               3,   6,   9,  12,  12,   9,   6,   3,
  969.               2,   4,   6,   8,   8,   6,   4,   2,
  970.               1,   2,   3,   4,   4,   3,   2,   1,
  971.               0,   0,   0, -20, -20,   0,   0,   0,
  972.               0,   0,   0,   0,   0,   0,   0,   0
  973.         };
  974.  
  975.     IntCopy (&pawn_pcsq[0],&_pawn_pcsq[0],64);
  976.  
  977.     int _kingside_pawn_pcsq[64]= {
  978.               0,   0,   0,   0,   0,   0,   0,   0,
  979.               0,   0,   0,   0,   0,   0,   0,   0,
  980.               0,   0,   0,   0,   0,   0,   0,   0,
  981.               0,   0,   0,   0,   0,   0,   0,   0,
  982.               0,   0,   0,   0,   0,   5,   5,   5,
  983.               0,   0,   0,   0,   0,  10,  10,  10,
  984.               0,   0,   0,   0,   0,  20,  20,  20,
  985.               0,   0,   0,   0,   0,   0,   0,   0
  986.         };
  987.  
  988.     IntCopy (&kingside_pawn_pcsq[0],&_kingside_pawn_pcsq[0],64);
  989.  
  990.     int _queenside_pawn_pcsq[64]= {
  991.               0,   0,   0,   0,   0,   0,   0,   0,
  992.               0,   0,   0,   0,   0,   0,   0,   0,
  993.               0,   0,   0,   0,   0,   0,   0,   0,
  994.               0,   0,   0,   0,   0,   0,   0,   0,
  995.               5,   5,   5,   0,   0,   0,   0,   0,
  996.              10,  10,  10,   0,   0,   0,   0,   0,
  997.              20,  20,  20,   0,   0,   0,   0,   0,
  998.               0,   0,   0,   0,   0,   0,   0,   0
  999.         };
  1000.  
  1001.     IntCopy (&queenside_pawn_pcsq[0],&_queenside_pawn_pcsq[0],64);
  1002.  
  1003.     int _minor_pcsq[64]= {
  1004.             -10, -10, -10, -10, -10, -10, -10, -10,
  1005.             -10,   0,   0,   0,   0,   0,   0, -10,
  1006.             -10,   0,   5,   5,   5,   5,   0, -10,
  1007.             -10,   0,   5,  10,  10,   5,   0, -10,
  1008.             -10,   0,   5,  10,  10,   5,   0, -10,
  1009.             -10,   0,   5,   5,   5,   5,   0, -10,
  1010.             -10,   0,   0,   0,   0,   0,   0, -10,
  1011.             -20, -20, -20, -20, -20, -20, -20, -20,
  1012.         };
  1013.  
  1014.     IntCopy (&minor_pcsq[0],&_minor_pcsq[0],64);
  1015.  
  1016.     int _king_pcsq[64]= {
  1017.             -40, -40, -40, -40, -40, -40, -40, -40,
  1018.             -40, -40, -40, -40, -40, -40, -40, -40,
  1019.             -40, -40, -40, -40, -40, -40, -40, -40,
  1020.             -40, -40, -40, -40, -40, -40, -40, -40,
  1021.             -40, -40, -40, -40, -40, -40, -40, -40,
  1022.             -40, -40, -40, -40, -40, -40, -40, -40,
  1023.             -20, -20, -20, -20, -20, -20, -20, -20,
  1024.             -10,   0,  10, -20,   0, -20,  10,   0
  1025.         };
  1026.  
  1027.     IntCopy (&king_pcsq[0],&_king_pcsq[0],64);
  1028.  
  1029.     int _endgame_king_pcsq[64]= {
  1030.              -5,  -5,  -5,  -5,  -5,  -5,  -5,  -5,
  1031.              -5,   0,   0,   0,   0,   0,   0,  -5,
  1032.              -5,   0,   5,   5,   5,   5,   0,  -5,
  1033.              -5,   0,   5,  10,  10,   5,   0,  -5,
  1034.              -5,   0,   5,  10,  10,   5,   0,  -5,
  1035.              -5,   0,   5,   5,   5,   5,   0,  -5,
  1036.              -5,   0,   0,   0,   0,   0,   0,  -5,
  1037.              -5,  -5,  -5,  -5,  -5,  -5,  -5,  -5
  1038.         };
  1039.  
  1040.     IntCopy (&endgame_king_pcsq[0],&_endgame_king_pcsq[0],64);
  1041.  
  1042.  
  1043.     int _mailbox[120]= {
  1044.              -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1045.              -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1046.              -1,  0,  1,  2,  3,  4,  5,  6,  7, -1,
  1047.              -1,  8,  9, 10, 11, 12, 13, 14, 15, -1,
  1048.              -1, 16, 17, 18, 19, 20, 21, 22, 23, -1,
  1049.              -1, 24, 25, 26, 27, 28, 29, 30, 31, -1,
  1050.              -1, 32, 33, 34, 35, 36, 37, 38, 39, -1,
  1051.              -1, 40, 41, 42, 43, 44, 45, 46, 47, -1,
  1052.              -1, 48, 49, 50, 51, 52, 53, 54, 55, -1,
  1053.              -1, 56, 57, 58, 59, 60, 61, 62, 63, -1,
  1054.              -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  1055.              -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
  1056.         };
  1057.  
  1058.     IntCopy (&mailbox[0],&_mailbox[0],120);
  1059.  
  1060.  
  1061.     int _mailbox64[64]= {
  1062.             21, 22, 23, 24, 25, 26, 27, 28,
  1063.             31, 32, 33, 34, 35, 36, 37, 38,
  1064.             41, 42, 43, 44, 45, 46, 47, 48,
  1065.             51, 52, 53, 54, 55, 56, 57, 58,
  1066.             61, 62, 63, 64, 65, 66, 67, 68,
  1067.             71, 72, 73, 74, 75, 76, 77, 78,
  1068.             81, 82, 83, 84, 85, 86, 87, 88,
  1069.             91, 92, 93, 94, 95, 96, 97, 98
  1070.         };
  1071.  
  1072.     IntCopy (&mailbox64[0],&_mailbox64[0],64);
  1073.  
  1074.     slide[0]=FALSE;
  1075.     slide[1]=FALSE;
  1076.     slide[2]=TRUE;
  1077.     slide[3]=TRUE;
  1078.     slide[4]=TRUE;
  1079.     slide[5]=FALSE;
  1080.  
  1081.     int _offsets[6]= {
  1082.             0, 8, 4, 4, 8, 8
  1083.         };
  1084.  
  1085.     IntCopy (&offsets[0],&_offsets[0],6);
  1086.  
  1087.  
  1088.     int _offset[6][8]={
  1089.             {0, 0, 0, 0, 0, 0, 0, 0,},
  1090.             {-21, -19, -12, -8, 8, 12, 19, 21,},
  1091.             {-11, -9, 9, 11, 0, 0, 0, 0,},
  1092.             {-10, -1, 1, 10, 0, 0, 0, 0,},
  1093.             {-11, -10, -9, -1, 1, 9, 10, 11,},
  1094.             {-11, -10, -9, -1, 1, 9, 10, 11}
  1095.         };
  1096.  
  1097.     IntCopy (&offset[0][0],&_offset[0][0],48);
  1098.  
  1099.     int _castle_mask[64]= {
  1100.              7, 15, 15, 15,  3, 15, 15, 11,
  1101.             15, 15, 15, 15, 15, 15, 15, 15,
  1102.             15, 15, 15, 15, 15, 15, 15, 15,
  1103.             15, 15, 15, 15, 15, 15, 15, 15,
  1104.             15, 15, 15, 15, 15, 15, 15, 15,
  1105.             15, 15, 15, 15, 15, 15, 15, 15,
  1106.             15, 15, 15, 15, 15, 15, 15, 15,
  1107.             13, 15, 15, 15, 12, 15, 15, 14
  1108.         };
  1109.  
  1110.     IntCopy (&castle_mask[0],&_castle_mask[0],64);
  1111.  
  1112.     int _value[6]= {
  1113.             100, 300, 300, 500, 900, 10000
  1114.         };
  1115.  
  1116.     IntCopy (&value[0],&_value[0],6);
  1117.  
  1118.     piece_char[0]='P';
  1119.     piece_char[1]='N';
  1120.     piece_char[2]='B';
  1121.     piece_char[3]='R';
  1122.     piece_char[4]='Q';
  1123.     piece_char[5]='K';
  1124.  
  1125.     int _init_color[64]= {
  1126.             1, 1, 1, 1, 1, 1, 1, 1,
  1127.             1, 1, 1, 1, 1, 1, 1, 1,
  1128.             6, 6, 6, 6, 6, 6, 6, 6,
  1129.             6, 6, 6, 6, 6, 6, 6, 6,
  1130.             6, 6, 6, 6, 6, 6, 6, 6,
  1131.             6, 6, 6, 6, 6, 6, 6, 6,
  1132.             0, 0, 0, 0, 0, 0, 0, 0,
  1133.             0, 0, 0, 0, 0, 0, 0, 0
  1134.         };
  1135.  
  1136.     IntCopy (&init_color[0],&_init_color[0],64);
  1137.  
  1138.     int _init_piece[64]= {
  1139.             3, 1, 2, 4, 5, 2, 1, 3,
  1140.             0, 0, 0, 0, 0, 0, 0, 0,
  1141.             6, 6, 6, 6, 6, 6, 6, 6,
  1142.             6, 6, 6, 6, 6, 6, 6, 6,
  1143.             6, 6, 6, 6, 6, 6, 6, 6,
  1144.             6, 6, 6, 6, 6, 6, 6, 6,
  1145.             0, 0, 0, 0, 0, 0, 0, 0,
  1146.             3, 1, 2, 4, 5, 2, 1, 3
  1147.         };
  1148.  
  1149.     IntCopy (&init_piece[0],&_init_piece[0],64);
  1150. }
  1151. //-----------------------------------------------------------------------
  1152.